﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Serialization;
using BeeCoders.Tools.ControlCanvas.Controls;
using BeeCoders.Tools.ControlCanvas.Infrastructure;

namespace BeeCoders.Tools.ControlCanvas
{
	[Serializable()]
	public class ControlCollection : ObservableCollectionEx<ControlViewModel>
	{
		public ControlCollection() : base()
		{
		 
		}
	}

	public class ObservableCollectionEx<T> : ObservableCollection<T> where T : INotifyPropertyChanged
	{
		protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
		{
			Unsubscribe(e.OldItems);
			Subscribe(e.NewItems);
			base.OnCollectionChanged(e);
		}

		protected override void ClearItems()
		{
			foreach (T element in this)
				element.PropertyChanged -= ContainedElementChanged;

			base.ClearItems();
		}

		private void Subscribe(IList iList)
		{
			if (iList != null)
			{
				foreach (T element in iList)
					element.PropertyChanged += ContainedElementChanged;
			}
		}

		private void Unsubscribe(IList iList)
		{
			if (iList != null)
			{
				foreach (T element in iList)
					element.PropertyChanged -= ContainedElementChanged;
			}
		}

		private void ContainedElementChanged(object sender, PropertyChangedEventArgs e)
		{
			OnPropertyChanged(e);
		}
	}

	[Serializable()]
	public class ControlViewModel : ViewModelBase
	{

		#region IsDirty

		private bool isDirty;

		public bool IsDirty
		{
			get { return isDirty; }
			set
			{
				if (value == isDirty) return;
				isDirty = value;
				RaisePropertyChanged("IsDirty");

			}
		}

		#endregion

		#region Id

		private int id;

		public int Id
		{
			get { return id; }
			set
			{
				if (value == id) return;
				id = value;
				RaisePropertyChanged("Id");

			}
		}

		#endregion

		#region Name
		private string name;

		public string Name
		{
			get { return name; }
			set
			{
				if (value == name) return;
				name = value;
				RaisePropertyChanged("Name");

			}
		}
		#endregion

		#region Prompt

		private string prompt;

		public string Prompt
		{
			get { return prompt; }
			set
			{
				if (value == prompt) return;
				prompt = value;
				RaisePropertyChanged("Prompt");

				IsDirty = true;
			}
		}

		#endregion

		#region ParameterValue

		public object ParameterValue
		{
			get
			{
				if (DefaultValues == null) return null;

				if (DefaultValues.Count == 0) return null;

				return DefaultValues[0];
			}
			set
			{
				if (DefaultValues == null) DefaultValues = new ObservableCollection<object>();

				if (DefaultValues.Count == 0) DefaultValues.Add(value);

				DefaultValues[0] = value;

				RaisePropertyChanged("ParameterValue");
				RaisePropertyChanged("SelectedValue");
				RaisePropertyChanged("IsRequired");

				IsDirty = true;

			}
		}

		public string ParameterValueString
		{
			get
			{
				var type = ParameterValue.GetType();

				if (ParameterValue.GetType() == typeof(string))
				{
					return ParameterValue.ToString();
				}
				if (ParameterValue.GetType() == typeof(DateTime))
				{
					return ParameterValue.ToString();
				}
				if (ParameterValue.GetType() == typeof(int))
				{
					return ParameterValue.ToString();
				}
				if (ParameterValue.GetType() == typeof(double))
				{
					return ParameterValue.ToString();
				}
				if (ParameterValue.GetType() == typeof(float))
				{
					return ParameterValue.ToString();
				}
				return "todo";
			}
		}

		#endregion

		#region ParameterMask

		private string parameterMask;

		public string ParameterMask
		{
			get { return parameterMask; }
			set
			{
				if (value == parameterMask) return;
				parameterMask = value;
				RaisePropertyChanged("ParameterMask");

			}
		}

		#endregion

		#region DefaultValues

		private ObservableCollection<object> defaultValues;

		public ObservableCollection<object> DefaultValues
		{
			get { return defaultValues; }
			set
			{
				if (value == defaultValues) return;
				defaultValues = value;
				RaisePropertyChanged("DefaultValues");
				RaisePropertyChanged("ParameterValue");
				RaisePropertyChanged("SelectedValue");

			}
		}

		#endregion

		#region MultiValue

		private bool multiValue;

		public bool MultiValue
		{
			get { return multiValue; }
			set
			{
				if (value == multiValue) return;
				multiValue = value;
				RaisePropertyChanged("MultiValue");

			}
		}

		#endregion

		#region AllowBlank

		private bool allowBlank;

		public bool AllowBlank
		{
			get { return allowBlank; }
			set
			{
				if (value == allowBlank) return;
				allowBlank = value;
				RaisePropertyChanged("AllowBlank");
				RaisePropertyChanged("IsRequired");

			}
		}

		#endregion

		#region Nullable

		private bool nullable;

		public bool Nullable
		{
			get { return nullable; }
			set
			{
				if (value == nullable) return;
				nullable = value;
				RaisePropertyChanged("Nullable");
				RaisePropertyChanged("IsRequired");

			}
		}

		#endregion

		#region TabOrder

		private int tabOrder;

		public int TabOrder
		{
			get { return tabOrder; }
			set
			{
				if (value == tabOrder) return;
				tabOrder = value;
				RaisePropertyChanged("TabOrder");

				if (Node != null)
				{
					if (Node.Content != null)
					{
						switch (ControlType)
						{
							case ControlTypeEnum.TextBox:
								(Node.Content as TextBoxControl).TabIndex = TabOrder;
								break;
							case ControlTypeEnum.NumericTextBox:
								(Node.Content as NumericTextBoxControl).TabIndex = TabOrder;
								break;
							case ControlTypeEnum.CheckBox:
								(Node.Content as CheckBoxControl).TabIndex = TabOrder;
								break;
							case ControlTypeEnum.DropDown:
								(Node.Content as DropDownControl).TabIndex = TabOrder;
								break;
							case ControlTypeEnum.DateTimePicker:
								(Node.Content as DateTimeControl).TabIndex = TabOrder;
								break;
							case ControlTypeEnum.Calendar:
								(Node.Content as CalendarControl).TabIndex = TabOrder;
								break;
							case ControlTypeEnum.Label:
								(Node.Content as LabelControl).TabIndex = TabOrder;
								break;
							default:
								(Node.Content as TextBoxControl).TabIndex = TabOrder;
								break;

						}
					}
				}

			}
		}

		#endregion

		#region IsRequired


		public bool IsRequired
		{
			get
			{
				if ((!AllowBlank) && (ParameterValue == null)) return true;

				if ((!Nullable) && (ParameterValue == null)) return true;

				return false;
			}

		}

		#endregion

		#region ValidValues

		private ObservableCollection<ValueViewModel> validValues;

		public ObservableCollection<ValueViewModel> ValidValues
		{
			get { return validValues; }
			set
			{
				if (value == validValues) return;
				validValues = value;
				RaisePropertyChanged("ValidValues");

			}
		}

		#endregion

		//#region ValidValuesQueryBased

		//private bool validValuesQueryBased;

		//public bool ValidValuesQueryBased
		//{
		//    get { return validValuesQueryBased; }
		//    set
		//    {
		//        if (value == validValuesQueryBased) return;
		//        validValuesQueryBased = value;
		//        RaisePropertyChanged("ValidValuesQueryBased");

		//    }
		//}

		//#endregion

		//#region DefaultValuesQueryBased

		//private bool defaultValuesQueryBased;

		//public bool DefaultValuesQueryBased
		//{
		//    get { return defaultValuesQueryBased; }
		//    set
		//    {
		//        if (value == defaultValuesQueryBased) return;
		//        defaultValuesQueryBased = value;
		//        RaisePropertyChanged("DefaultValuesQueryBased");

		//    }
		//}

		//#endregion

		//#region ValidValuesQuery

		//private DataSetViewModel validValuesQuery;

		//public DataSetViewModel ValidValuesQuery
		//{
		//    get { return validValuesQuery; }
		//    set
		//    {
		//        if (value == validValuesQuery) return;
		//        validValuesQuery = value;
		//        RaisePropertyChanged("ValidValuesQuery");

		//    }
		//}

		//#endregion

		//#region DefaultValuesQuery

		//private DataSetViewModel defaultValuesQuery;

		//public DataSetViewModel DefaultValuesQuery
		//{
		//    get { return defaultValuesQuery; }
		//    set
		//    {
		//        if (value == defaultValuesQuery) return;
		//        defaultValuesQuery = value;
		//        RaisePropertyChanged("DefaultValuesQuery");

		//    }
		//}

		//#endregion

		#region IsLabel

		private bool isLabel;

		public bool IsLabel
		{
			get { return isLabel; }
			set
			{
				if (value == isLabel) return;
				isLabel = value;
				RaisePropertyChanged("IsLabel");

			}
		}

		#endregion

		#region IsParameter

		private bool isParameter;

		public bool IsParameter
		{
			get { return isParameter; }
			set
			{
				if (value == isParameter) return;
				isParameter = value;
				RaisePropertyChanged("IsParameter");

			}
		}

		#endregion


		#region PromptUser

		private bool promptUser;

		public bool PromptUser
		{
			get { return promptUser; }
			set
			{
				if (value == promptUser) return;
				promptUser = value;
				RaisePropertyChanged("PromptUser");
				IsDirty = true;
			}
		}

		#endregion




		#region Width

		private int width;

		public int Width
		{
			get { return width; }
			set
			{
				if (value == width) return;
				width = value;
				RaisePropertyChanged("Width");

			}
		}

		#endregion

		#region Height

		private int height;

		public int Height
		{
			get { return height; }
			set
			{
				if (value == height) return;
				height = value;
				RaisePropertyChanged("Height");

			}
		}

		#endregion



		#region IsInDesign

		private bool isInDesign;

		public bool IsInDesign
		{
			get { return isInDesign; }
			set
			{
				if (value == isInDesign) return;
				isInDesign = value;
				RaisePropertyChanged("IsInDesign");

				IsDirty = true;
			}
		}

		#endregion

		#region LeftPosition

		private int? leftPosition;

		public int? LeftPosition
		{
			get { return leftPosition; }
			set
			{
				if (value == leftPosition) return;
				leftPosition = value;
				RaisePropertyChanged("LeftPosition");

			}
		}

		#endregion

		#region TopPosition

		private int? topPosition;

		public int? TopPosition
		{
			get { return topPosition; }
			set
			{
				if (value == topPosition) return;
				topPosition = value;
				RaisePropertyChanged("TopPosition");

			}
		}

		#endregion

		#region LinkedControl

		private ControlViewModel linkedControl;

		public ControlViewModel LinkedControl
		{
			get { return linkedControl; }
			set
			{
				if (value == linkedControl) return;
				linkedControl = value;
				RaisePropertyChanged("LinkedControl");

			}
		}

		#endregion



		#region ControlType

		private ControlTypeEnum controlType;

		public ControlTypeEnum ControlType
		{
			get { return controlType; }
			set
			{
				if (value == controlType) return;
				controlType = value;
				RaisePropertyChanged("ControlType");

			}
		}

		#endregion

		#region path

		private string path;

		public string Path
		{
			get { return path; }
			set
			{
				if (value == path) return;
				path = value;
				RaisePropertyChanged("Path");

			}
		}

		#endregion

		#region SetDefaultParameters,SetDefaultParameters
		public void SetDefaultParameters(List<string> defaultValuesList)
		{
			if (defaultValuesList == null) return;

			DefaultValues = new ObservableCollection<object>();
			foreach (string defaultValue in defaultValuesList)
			{
				DefaultValues.Add(defaultValue);
			}
		}

		public void SetDefaultParameters(string[] defaultValuesList)
		{
			if (defaultValuesList == null) return;

			SetDefaultParameters(new List<string>(defaultValuesList));

		}

	  
		#endregion

		[XmlIgnore]
		public DesignerItem Node { get; set; }

		[XmlIgnore]
		public ViewModelBase ParentViewModel { get; set; }

		#region ctor
		public ControlViewModel()
		{


		}

	  
		#endregion

	  



		public DesignerItem BuildNode(bool isInDesignMode)
		{
			Node = new DesignerItem(this);
			IsInDesign = isInDesignMode;
		
			switch (ControlType)
			{
				case ControlTypeEnum.TextBox:
					Node.Content = new TextBoxControl();
					(Node.Content as TextBoxControl).IsHitTestVisible = true;
					(Node.Content as TextBoxControl).IsTabStop = true;
					Node.MinWidth = 75;
					Node.MinHeight = 28;
					(Node.Content as TextBoxControl).TabIndex = TabOrder;
					break;
				case ControlTypeEnum.NumericTextBox:
					Node.Content = new NumericTextBoxControl();
					(Node.Content as NumericTextBoxControl).IsHitTestVisible = true;
					(Node.Content as NumericTextBoxControl).IsTabStop = true;
					Node.MinWidth = 75;
					Node.MinHeight = 28;
					(Node.Content as NumericTextBoxControl).TabIndex = TabOrder;
					break;
				case ControlTypeEnum.CheckBox:
					Node.Content = new CheckBoxControl();
					(Node.Content as CheckBoxControl).IsHitTestVisible = true;
					(Node.Content as CheckBoxControl).IsTabStop = true;
					Node.MinWidth = 75;
					Node.MinHeight = 28;
					(Node.Content as CheckBoxControl).TabIndex = TabOrder;
					break;
				case ControlTypeEnum.DropDown:
					Node.Content = new DropDownControl();
					(Node.Content as DropDownControl).IsHitTestVisible = true;
					(Node.Content as DropDownControl).IsTabStop = true;
					Node.MinWidth = 75;
					Node.MinHeight = 28;
					(Node.Content as DropDownControl).TabIndex = TabOrder;
					break;
				case ControlTypeEnum.DateTimePicker:
					Node.Content = new DateTimeControl();
					(Node.Content as DateTimeControl).IsHitTestVisible = true;
					(Node.Content as DateTimeControl).IsTabStop = true;
					Node.MinWidth = 75;
					Node.MinHeight = 28;
					(Node.Content as DateTimeControl).TabIndex = TabOrder;
					break;
				case ControlTypeEnum.Calendar:
					Node.Content = new CalendarControl();
					(Node.Content as CalendarControl).IsHitTestVisible = true;
					(Node.Content as CalendarControl).IsTabStop = true;
					Node.MaxWidth = 200;
					Node.MaxHeight = 170;
					Node.MinWidth = 200;
					Node.MinHeight = 170;
					(Node.Content as CalendarControl).TabIndex = TabOrder;
					break;
				case ControlTypeEnum.Label:
					Node.Content = new LabelControl();
					(Node.Content as LabelControl).IsHitTestVisible = true;
					(Node.Content as LabelControl).IsTabStop = false;
					Node.MinWidth = 75;
					Node.MinHeight = 28;
					(Node.Content as LabelControl).TabIndex = TabOrder;
					break;
				default:
					Node.Content = new TextBoxControl();
					(Node.Content as TextBoxControl).IsHitTestVisible = true;
					(Node.Content as TextBoxControl).IsTabStop = true;
					(Node.Content as TextBoxControl).TabIndex = TabOrder;
					break;

			}
			Node.DataContext = this;



			Node.IsTabStop = false;

			Node.HorizontalContentAlignment = HorizontalAlignment.Stretch;
			Node.VerticalContentAlignment = VerticalAlignment.Stretch;


			Node.Width = Width;
			Node.Height = Height;

			if (LeftPosition == null) LeftPosition = 10;
			if (TopPosition == null) TopPosition = 10;

			Canvas.SetLeft(Node, (double)LeftPosition);
			Canvas.SetTop(Node, (double)TopPosition);

			Panel.SetZIndex(Node, 100);

			IsDirty = false;
			return Node;

		}

		public override string ToString()
		{
			return string.Format("{0} {1}", Name, Path);
		}

	}

	public class ControlViewModelDemo : ControlViewModel
	{
		public ControlViewModelDemo()
		{
			Id = 1;
			Width = 100;
			Name = "Customer ID:";
			Prompt = "This is the prompt";
			ParameterValue = "Test";

			ControlType = ControlTypeEnum.DropDown;

			AllowBlank = false;
			IsInDesign = true;
			MultiValue = true;
			Nullable = false;


		}
	}
}
